/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package business.dataVisualization.chart;

import business.algorithm.technicalIndicator.AbstractTechnicalIndicator;
import business.algorithm.technicalIndicator.PointEntry;
import dataAccess.databaseManagement.entity.PriceEntity;
import java.awt.BasicStroke;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Random;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.DeviationRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.YIntervalSeries;
import org.jfree.data.xy.YIntervalSeriesCollection;

/**
 *
 * @author Dinh
 */
public abstract class VisulizationChart {

    public static final ChartStyle[] CHART_STYLES = {
        new ChartStyle(LineChart.class),
        new ChartStyle(CandleStickChart.class)};
    protected static final ArrayList<Color> techIndicator0LineColors = new ArrayList<Color>();
    protected static final ArrayList<Color> techIndicator1LineColors = new ArrayList<Color>();
    protected JFreeChart chart;
    protected XYDataset techIndicatorType0Dataset = new YIntervalSeriesCollection();
    protected XYDataset techIndicatorType1Dataset = new YIntervalSeriesCollection();
    private HashMap<Object, Integer> mappingTechIndicatorSeries = new HashMap<Object, Integer>();

//	public void addOrders(AbstractTechnicalIndicator decAlgo,
//			ArrayList<Order> orders) {
//
//		// Utility.debug(orders.size());
//
//		TimeSeries buySeries = new TimeSeries("Buy Signals - "
//				+ decAlgo.toString());
//		TimeSeries sellSeries = new TimeSeries("Sell Signals - "
//				+ decAlgo.toString());
//
//		for (Order order : orders) {
//			if (order.isOrderType() == Order.ORDER_BUY) {
//				buySeries.add(new Day(order.getDate()), order.getPrice());
//			} else {
//				sellSeries.add(new Day(order.getDate()), order.getPrice());
//			}
//		}
//
//		mappingOrderSeries.put(decAlgo, markPointsDataset.getSeriesCount());
//		((TimeSeriesCollection) markPointsDataset).addSeries(buySeries);
//		((TimeSeriesCollection) markPointsDataset).addSeries(sellSeries);
//
//		XYPlot plot = chart.getXYPlot();
//		XYLineAndShapeRenderer xYLineAndShapeRenderer = (XYLineAndShapeRenderer) plot
//				.getRenderer(3);
//		xYLineAndShapeRenderer.setSeriesLinesVisible(
//				markPointsDataset.getSeriesCount() - 1, false);
//		xYLineAndShapeRenderer.setSeriesLinesVisible(
//				markPointsDataset.getSeriesCount() - 2, false);
//	}
//	public void removeOrder(AbstractTechnicalIndicator decAlgo) {
//		if (mappingOrderSeries.get(decAlgo) == null) {
//			return;
//		}
//
//		((TimeSeriesCollection) markPointsDataset)
//				.removeSeries(mappingOrderSeries.get(decAlgo));
//		((TimeSeriesCollection) markPointsDataset)
//				.removeSeries(mappingOrderSeries.get(decAlgo));
//
//		mappingOrderSeries.remove(decAlgo);
//	}
//
//	public void removeAllOrders() {
//		((TimeSeriesCollection) markPointsDataset).removeAllSeries();
//		mappingOrderSeries.clear();
//	}
    public void addTechnicalIndicator(AbstractTechnicalIndicator indicator, ArrayList<ArrayList<PointEntry>> output) {

        YIntervalSeries yintervalseries = new YIntervalSeries("Indicator - "
                + indicator.toString());

        if (output.size() == 1) {
            for (PointEntry entry : output.get(0)) {
                yintervalseries.add(entry.getDate().getTime(), entry.getValue(),
                        entry.getValue(), entry.getValue());
            }
        } else if (output.size() == 3) {
            for (int i = 0; i < output.get(0).size(); ++i) {
                yintervalseries.add(output.get(0).get(i).getDate().getTime(), output.get(0).get(i).getValue(),
                        output.get(1).get(i).getValue(), output.get(2).get(i).getValue());
            }
        }

        if (indicator.getType() == AbstractTechnicalIndicator.PRICE_CHART) {
            XYPlot plot = (XYPlot) ((CombinedDomainXYPlot) chart.getPlot()).getSubplots().get(0);
            mappingTechIndicatorSeries.put(indicator, techIndicatorType0Dataset.getSeriesCount());
            ((YIntervalSeriesCollection) techIndicatorType0Dataset).addSeries(yintervalseries);

            DeviationRenderer deviationRenderer = (DeviationRenderer) plot.getRenderer(2);
            deviationRenderer.setSeriesStroke(
                    techIndicatorType0Dataset.getSeriesCount() - 1, new BasicStroke(2F, 1,
                    1));

            Random random = new Random(Calendar.getInstance().getTimeInMillis());
            while (techIndicator0LineColors.size() < techIndicatorType0Dataset.getSeriesCount()) {
                Color color = new Color(random.nextInt(256), random.nextInt(256),
                        random.nextInt(256));
                while (techIndicator0LineColors.contains(color) || techIndicator1LineColors.contains(color)) {
                    color = new Color(random.nextInt(256), random.nextInt(256),
                            random.nextInt(256));
                }
                techIndicator0LineColors.add(color);
            }

            deviationRenderer.setSeriesFillPaint(
                    techIndicatorType0Dataset.getSeriesCount() - 1, techIndicator0LineColors.get(techIndicatorType0Dataset.getSeriesCount() - 1));
            deviationRenderer.setSeriesPaint(
                    techIndicatorType0Dataset.getSeriesCount() - 1, techIndicator0LineColors.get(techIndicatorType0Dataset.getSeriesCount() - 1));
        } else if (indicator.getType() == AbstractTechnicalIndicator.NOT_PRICE_CHART) {
            XYPlot plot = (XYPlot) ((CombinedDomainXYPlot) chart.getPlot()).getSubplots().get(1);
            mappingTechIndicatorSeries.put(indicator, techIndicatorType1Dataset.getSeriesCount());
            ((YIntervalSeriesCollection) techIndicatorType1Dataset).addSeries(yintervalseries);

            DeviationRenderer deviationRenderer = (DeviationRenderer) plot.getRenderer(2);
            deviationRenderer.setSeriesStroke(
                    techIndicatorType1Dataset.getSeriesCount() - 1, new BasicStroke(2F, 1,
                    1));

            Random random = new Random(Calendar.getInstance().getTimeInMillis());
            while (techIndicator1LineColors.size() < techIndicatorType1Dataset.getSeriesCount()) {
                Color color = new Color(random.nextInt(256), random.nextInt(256),
                        random.nextInt(256));
                while (techIndicator0LineColors.contains(color) || techIndicator1LineColors.contains(color)) {
                    color = new Color(random.nextInt(256), random.nextInt(256),
                            random.nextInt(256));
                }
                techIndicator1LineColors.add(color);
            }
            
            deviationRenderer.setSeriesFillPaint(
                    techIndicatorType1Dataset.getSeriesCount() - 1, techIndicator1LineColors.get(techIndicatorType1Dataset.getSeriesCount() - 1));
            deviationRenderer.setSeriesPaint(
                    techIndicatorType1Dataset.getSeriesCount() - 1, techIndicator1LineColors.get(techIndicatorType1Dataset.getSeriesCount() - 1));

        }

    }

    public void removeTechnicalIndicator(AbstractTechnicalIndicator abstractTechnicalIndicator) {
        if (mappingTechIndicatorSeries.get(abstractTechnicalIndicator) == null) {
            return;
        }

        if (abstractTechnicalIndicator.getType() == AbstractTechnicalIndicator.PRICE_CHART) {
            ((YIntervalSeriesCollection) techIndicatorType0Dataset).removeSeries(mappingTechIndicatorSeries.get(abstractTechnicalIndicator));
        } else if (abstractTechnicalIndicator.getType() == AbstractTechnicalIndicator.NOT_PRICE_CHART) {
            ((YIntervalSeriesCollection) techIndicatorType1Dataset).removeSeries(mappingTechIndicatorSeries.get(abstractTechnicalIndicator));
        }

        mappingTechIndicatorSeries.remove(abstractTechnicalIndicator);
    }

    public void removeAllPredictionPrice() {
        ((YIntervalSeriesCollection) techIndicatorType0Dataset).removeAllSeries();
        ((YIntervalSeriesCollection) techIndicatorType1Dataset).removeAllSeries();
        mappingTechIndicatorSeries.clear();
    }

    public JFreeChart getChart() {
        return chart;
    }

    public abstract void setPrices(ArrayList<PriceEntity> prices);

    public abstract void initalChart();

    public abstract void updateChart();
}
